package com.itmuch;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.Resource;
import org.springframework.jdbc.datasource.init.DataSourceInitializer;
import org.springframework.jdbc.datasource.init.DatabasePopulator;
import org.springframework.jdbc.datasource.init.ResourceDatabasePopulator;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.security.oauth2.provider.token.store.JdbcTokenStore;
import javax.sql.DataSource;

/**
 * EnableAuthorizationServer
 * AuthorizationServerSecurityConfigurer
 * Created by xi on 2017/5/30.
 * AuthorizationEndpoint ：用于服务请求进行授权 /oauth/authorize
 * TokenEndpoint ：获取访问令牌 : /oauth/token
 * AuthorizationServerTokenServices:管理这个令牌（创建令牌）
 *以下过滤器需要实现一个OAuth 2.0资源服务器:
 的 OAuth2AuthenticationProcessingFilter 用于加载请求的身份验证身份验证访问令牌。

 AuthorizationServerEndpointsConfigurer:可以配置访问类型
 */
@Configuration
public class AuthorizationServerConfiguration extends AuthorizationServerConfigurerAdapter {

    @Autowired
    private AuthenticationManager authManager;

    @Autowired
    private DataSource dataSource;

    //spirng会读取这个配置文件，然后尝试帮你生成Resource对象
    @Value("classpath:schema.sql")
    private Resource schemaScript;

    @Value("classpath:data.sql")
    private Resource dataScript;

    @Bean
    public DataSourceInitializer dataSourceInitializer(final DataSource dataSource) {
        final DataSourceInitializer initializer = new DataSourceInitializer();
        initializer.setDataSource(dataSource);
        initializer.setDatabasePopulator(databasePopulator());
        return initializer;
    }

    private DatabasePopulator databasePopulator() {
        final ResourceDatabasePopulator populator = new ResourceDatabasePopulator();
        populator.addScript(schemaScript);
        populator.addScript(dataScript);
        return populator;
    }


    //server的安全性的配置 定义了安全限制令牌端点
    @Override
    public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
        security
                .checkTokenAccess("permitAll()")//允许所有进来的进行Acess——toke
                .allowFormAuthenticationForClients();//允许form表单的access_token来拿的;
    }

    //关于clientApp 的配置，就是自身服务器的App的配置，或者是第三方的App的配置
    //可以是自身的应用。 客户端身份识别
    //我们必须分配 client_id, client_secret才行。
    //JdbcClientDetailsService
    //配置客户端配置的detailService 从哪里验证的方案：
    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
        clients.jdbc(dataSource);
        //客户端身份识别是放到数据库区的
        //testByInMemory(clients);
    }

    //server入口点的配置 定义授权和令牌发布端口和令牌服务
    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
        endpoints.authenticationManager(authManager).tokenStore(tokenStore());
    }

    //产生一个Bean ,这里讲了怎么存储token,其实还有一种jwt方式来存储token,只是每次都要加密，解密；
    @Bean
    public TokenStore tokenStore() {
        return new JdbcTokenStore(dataSource);
    }


    private void testByInMemory(ClientDetailsServiceConfigurer clients) throws Exception{
        //授权模式：账号密码模式，
        clients.inMemory().withClient("client-id").secret("client-secrect").authorizedGrantTypes("password")
                .scopes("read,write,trust");
    }
}
